package scicalc;

public class Matrix {
    // 常量0
    public static final double ZERO = 0;

    // 常量1
    public static final double ONE = 1;

    /**
     * 生成n行n列的单位矩阵
     *
     * @param n
     * @return
     */
    public static double[][] identityMatrix(int n) {
        double[][] matrix = new double[n][n];
        for (int i = 0; i < n; i++) {
            matrix[i][i] = ONE;
        }
        return matrix;
    }

    /**
     * 求矩阵a的转制a^T
     *
     * @param a
     * @return
     */
    public static double[][] T(double[][] a) {
        double[][] matrix = new double[a[0].length][a.length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[i].length; j++)
                matrix[j][i] = a[i][j];
        return matrix;
    }

    /**
     * 求余子式Aij
     *
     * @param a
     * @param i
     * @param j
     * @return
     */
    public static double[][] minor(double[][] a, int i, int j) {
        int size = a.length;
        double[][] res = new double[size - 1][size - 1];
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {
                //left up
                if (x < i && y < j) res[x][y] = a[x][y];
                    //right up
                else if (x < i && y > j) res[x][y - 1] = a[x][y];
                    //left bottom
                else if (x > i && y < j) res[x - 1][y] = a[x][y];
                    //right bottom
                else if (x > i && y > j) res[x - 1][y - 1] = a[x][y];
            }
        }
        return res;
    }

    /**
     * 求行列式|a|
     *
     * @param a
     * @return
     */
    public static double det(double[][] a) {
        if (a.length == 1)
            return a[0][0];
        double res = 0;
        for (int i = 0; i < a.length; i++)
            res += Calculate.pow(-1, i) * a[0][i] * det(minor(a, 0, i));
        return res;
    }

    /**
     * 求方阵a的逆 a^-1
     *
     * @param a
     * @return
     */
    public static double[][] inv(double[][] a) {
        int size = a.length;
        double[][] temp = new double[size][size];
        for (int i = 0; i < size; i++)
            for (int j = 0; j < size; j++)
                temp[i][j] = Calculate.pow(-1, i + j) * det(minor(a, i, j));
        double det = det(a);
        return Calculate.divide(Matrix.T(temp), det);
    }

    /**
     * 矩阵aXb
     *
     * @param a
     * @param b
     * @return
     */
    public static double[][] dot(double[][] a, double[][] b) {
        double[][] rs = new double[a.length][b[0].length];
        if (a[0].length!=b.length)
            System.out.println("err");
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                double sum = 0;
                for (int k = 0; k < b.length; k++) {
                    sum += a[i][k] * b[k][j];
                }
                rs[i][j] = sum;
            }
        }
        return rs;
    }

    /**
     * 将一位数组转为二维数组
     *
     * @param a
     * @return
     */
    public static double[][] arrayToMatrix(double[] a) {
        double[][] rs = new double[1][a.length];
        rs[0] = a;
        return rs;
    }
}
